package com.zoe.onelink.business.mybatis.interceptor;

import cn.hutool.core.util.ReflectUtil;
import com.baomidou.mybatisplus.extension.plugins.inner.InnerInterceptor;
import com.zoe.onelink.business.entity.AdvanceQuery;
import com.zoe.onelink.common.entity.IBaseEntity;
import com.zoe.onelink.logging.trace.util.SqlParserUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.ibatis.binding.MapperMethod;
import org.apache.ibatis.executor.Executor;
import org.apache.ibatis.mapping.BoundSql;
import org.apache.ibatis.mapping.MappedStatement;
import org.apache.ibatis.mapping.ResultMap;
import org.apache.ibatis.session.ResultHandler;
import org.apache.ibatis.session.RowBounds;
import org.springframework.core.Ordered;

import java.sql.SQLException;

/**
 * <p>标题: </p>
 * <p>描述: </p>
 * <p>版权: Copyright (c) 2022</p>
 * <p>公司: 智业软件股份有限公司</p>
 *
 * @version: 1.0
 * @author: ruansheng
 * @date: 2022-10-27
 */
@Slf4j
public class MybatisAdvanceQueryInnerInterceptor implements InnerInterceptor, Ordered {


    @Override
    public boolean willDoQuery(Executor executor, MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler, BoundSql boundSql) throws SQLException {
        AdvanceQuery advanceQuery = this.getAdvanceQuery(parameter);
        if (advanceQuery != null) {
            String advanceSql = this.getAdvanceSql(ms, boundSql, advanceQuery);
            ReflectUtil.setFieldValue(boundSql, "sql", advanceSql);
        }
        return true;
    }

    private String getAdvanceSql(MappedStatement ms, BoundSql boundSql, AdvanceQuery advanceQuery) {
        String sql = boundSql.getSql();
        // 判断是否将字段转换为驼峰，要不要用sql解析处理，先将返回值为实体转换，之后支持sql解析判断
        boolean changeLine = false;
        if (!ms.getResultMaps().isEmpty()) {
            ResultMap resultMap = ms.getResultMaps().get(0);
            Class<?> resultType = resultMap.getType();
            if (resultType != null) {
                if (IBaseEntity.class.isAssignableFrom(resultType) && sql.contains(".*")) {
                    changeLine = true;
                }
            }
        }
        return advanceQuery.getSql(sql, changeLine);
    }

    /**
     * 获取填充过参数的SQL语句
     */
    private String getFilledSql(MappedStatement mappedStatement, BoundSql boundSql) {
        try {
            return SqlParserUtil.fillSqlParam(mappedStatement.getConfiguration(), boundSql);
        } catch (Exception e) {
            log.warn("填充SQL语法参数失败:{}", e.getMessage());
        }
        return boundSql.getSql();
    }


    private AdvanceQuery getAdvanceQuery(Object parameter) {
        AdvanceQuery advanceQuery = null;
        if (parameter instanceof MapperMethod.ParamMap) {
            MapperMethod.ParamMap<?> parameterMap = (MapperMethod.ParamMap<?>) parameter;
            advanceQuery = (AdvanceQuery) parameterMap.values().stream()
                    .filter(value -> value instanceof AdvanceQuery)
                    .findFirst()
                    .orElse(null);
        }
        return advanceQuery;
    }

    @Override
    public int getOrder() {
        return HIGHEST_PRECEDENCE;
    }
}
